/**
 * Copyright 2018 lenos
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.jantd.modules.activiti.actlistener;


import java.util.List;

import cn.jantd.core.api.vo.Result;
import cn.jantd.modules.system.entity.SysRole;
import cn.jantd.modules.system.entity.SysUser;
import cn.jantd.modules.system.entity.SysUserRole;
import cn.jantd.modules.system.service.ISysUserRoleService;
import cn.jantd.modules.system.service.ISysUserService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.activiti.engine.IdentityService;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.persistence.entity.GroupEntity;
import org.activiti.engine.impl.persistence.entity.UserEntity;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author zhuxiaomeng
 * @date 2018/1/25.
 * @email 154040976@qq.com
 * <p>
 * 切入实现系统用户 角色 用户-角色 同步到 activiti 用户 组 用户组 同步到工作流,模块化 无侵入
 */
@Aspect
@Component
public class ListenUserRole {

    @Autowired
    IdentityService identityService;

    @Autowired
    ISysUserService userService;
    @Autowired
    ISysUserRoleService userRoleService;

    /**********************用户处理begin***************************/
    /**
     * 明确切入方法的参数
     *
     * @param joinPoint
     */
    @Around("execution(cn.jantd.core.api.vo.Result cn.jantd.modules.system.controller.SysUserController.edit(com.alibaba.fastjson.JSONObject))")
    public Object listenerUserUpdate(ProceedingJoinPoint joinPoint) throws Throwable {
        //更新前删除用户-角色数据
        JSONObject json = (JSONObject) joinPoint.getArgs()[0];
        SysUser user = JSON.parseObject(json.toJSONString(), SysUser.class);
        removeUser(user.getId());
        Object o = joinPoint.proceed(joinPoint.getArgs());
        Result result = (Result) o;
        if (result.isSuccess()) {
            String selectedRoles = json.getString("selectedroles");
            saveUser(user.getUsername(), selectedRoles.split(","));
        }
        return o;
    }

    /**
     * 新增用户监听 同步工作流用户表 环绕注解能得到 插入用户id 啊哈哈
     *
     * @param joinPoint
     */
    @Around("execution(cn.jantd.core.api.vo.Result cn.jantd.modules.system.controller.SysUserController.add(com.alibaba.fastjson.JSONObject))")
    public Object listenerUserInsert(ProceedingJoinPoint joinPoint) throws Throwable {
        Object o = joinPoint.proceed(joinPoint.getArgs());
        Result result = (Result) o;
        if (result.isSuccess()) {
            JSONObject json = (JSONObject) joinPoint.getArgs()[0];
            String selectedRoles = json.getString("selectedroles");
            SysUser user = JSON.parseObject(json.toJSONString(), SysUser.class);
            saveUser(user.getUsername(), selectedRoles.split(","));
        }
        return o;
    }

    @Around("execution(cn.jantd.core.api.vo.Result cn.jantd.modules.system.controller.SysUserController.delete(String))")
    public Object listenDelUser(ProceedingJoinPoint point) throws Throwable {
        Object[] args = point.getArgs();
        removeUser((String) args[0]);
        return point.proceed(point.getArgs());
    }

    private void removeUser(String userId) {
        //删除用户-组关联
        List<SysUserRole> list = userRoleService.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getId, userId));
        if (null != list && list.size() > 0) {
            for (SysUserRole e : list) {
                identityService.deleteMembership(e.getUserId(), e.getRoleId());
            }
        }
        identityService.deleteUser(userId);
    }

    /**
     * 保存进 activiti 用户 角色 用户角色中间表
     *
     * @param username
     */
    private void saveUser(String username, String[] roles) {
        SysUser user = userService.getUserByName(username);
        User au = new UserEntity();
        au.setId(user.getId());
        au.setFirstName(user.getRealname());
        au.setEmail(user.getEmail());
        identityService.saveUser(au);
        if (null != roles && roles.length > 0) {
            //再次关联
            for (String roleId : roles) {
                identityService.createMembership(user.getId(), roleId);
            }
        }
    }

    /**********************用户处理end***************************/


    /**********************角色处理begin***************************/
    @Around("execution(cn.jantd.core.api.vo.Result cn.jantd.modules.system.controller.SysRoleController.add(cn.jantd.modules.system.entity.SysRole))")
    public Object listenRoleInsert(ProceedingJoinPoint joinPoint) throws Throwable {
        Object o = joinPoint.proceed(joinPoint.getArgs());
        Result j = (Result) o;
        if (j.isSuccess()) {
            Object[] args = joinPoint.getArgs();
            saveRole((SysRole) args[0]);
        }
        return o;
    }

    @Around("execution(cn.jantd.core.api.vo.Result cn.jantd.modules.system.controller.SysRoleController.edit(cn.jantd.modules.system.entity.SysRole))")
    public Object listenRoleUpdate(ProceedingJoinPoint joinPoint) throws Throwable {
        SysRole role = (SysRole) joinPoint.getArgs()[0];
        identityService.deleteGroup(role.getId());
        Object o = joinPoint.proceed(joinPoint.getArgs());
        if (((Result) o).isSuccess()) {
            saveRole(role);
        }
        return o;
    }

    @Around("execution(cn.jantd.core.api.vo.Result cn.jantd.modules.system.controller.SysRoleController.delete(..))")
    public Object listenDelRole(ProceedingJoinPoint point) throws Throwable {
        Object o = point.proceed(point.getArgs());
        Result result = (Result) o;
        if (result.isSuccess()) {
            Object[] args = point.getArgs();
            identityService.deleteGroup((String) args[0]);
        }
        return o;
    }

    /**
     * 更新进组
     *
     * @param role
     */
    public void saveRole(SysRole role) {
        Group group = new GroupEntity();
        group.setId(role.getId());
        group.setName(role.getRoleName());
        identityService.saveGroup(group);
    }

    /**********************角色处理end***************************/
}
